use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::Instruction, rtda::Frame};

// Convert int to byte
#[derive(Debug, Default)]
pub struct I2B {}

impl Instruction for I2B {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let b = i & 0xff;
        stack.borrow_mut().push_int(b);
    }
}

// Convert int to char
#[derive(Debug, Default)]
pub struct I2C {}

impl Instruction for I2C {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let c = i & 0xffff;
        stack.borrow_mut().push_int(c);
    }
}

// Convert int to short
#[derive(Debug, Default)]
pub struct I2S {}

impl Instruction for I2S {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let s = i as i16;
        stack.borrow_mut().push_int(s as i32);
    }
}

// Convert int to long
#[derive(Debug, Default)]
pub struct I2L {}

impl Instruction for I2L {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let l = i as i64;
        stack.borrow_mut().push_long(l);
    }
}

// Convert int to float
#[derive(Debug, Default)]
pub struct I2F {}

impl Instruction for I2F {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let f = i as f32;
        stack.borrow_mut().push_float(f);
    }
}

// Convert int to double
#[derive(Debug, Default)]
pub struct I2D {}

impl Instruction for I2D {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let i = stack.borrow_mut().pop_int();
        let d = i as f64;
        stack.borrow_mut().push_double(d);
    }
}